package jp.co.toshiba.ffsa.service.cstp;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import jp.co.toshiba.ffsa.common.MakeHash;
import jp.co.toshiba.ffsa.entity.Information;
import jp.co.toshiba.ffsa.entity.User;
import jp.co.toshiba.ffsa.service.common.CommonService;
import jp.co.toshiba.ffsa.service.common.ConstantValue;

import org.seasar.extension.jdbc.JdbcManager;
import org.seasar.extension.jdbc.where.ComplexWhere;
import org.seasar.extension.jdbc.where.SimpleWhere;
import org.seasar.framework.container.SingletonS2Container;
import org.seasar.framework.container.factory.SingletonS2ContainerFactory;

/**
 * Topページビジネスロジック
 * @author npc
 */
public class Cstp101Service {
    private String emailAddress = "";
    private String password = "";
    private String userID = "";
    /** ユーザー権限 */
    private String authority = "";
    /** 同意フラグ */
    private String agreementFlag = "";

    private List<Information> informationList;

    /**
     * メールアドレスをセットする
     * @param emailAddress
     */
    public void setEmailAddress(String emailAddress){this.emailAddress = emailAddress;}
    /**
     * パスワードをセットする
     * @param password
     */
    public void setPassword(String password){this.password = password;}
    /**
     * ユーザー権限をセットする
     * @param authority
     */
    public void setAuthority(String authority) {this.authority = authority;}
    /**
     * 同意フラグをセットする
     * @param authority
     */
    public void setAgreementFlag(String agreementFlag) {this.agreementFlag = agreementFlag;}
    /**
     * メールアドレスを取得する
     * @return emailAddress
     */
    public String getEmailAddress(){return this.emailAddress;}
    /**
     * パスワードを取得する
     * @return password
     */
    public String getPassword(){return this.password;}
    /**
     * ユーザーIDを取得する
     * @return userID
     */
    public String getUserID(){return this.userID;}
    /**
     * ユーザー権限を取得する
     * @return
     */
    public String getAuthority() {return this.authority;}
    /**
     * 同意フラグを取得する
     * @return
     */
    public String getAgreementFlag() {return this.agreementFlag;}

    /**
     * ログイン処理を行う
     * @return
     * @throws Exception
     */
    public String loginLogic() throws Exception{
        String retStr = "";
        try{
            retStr = this.getUser();
        }catch(Exception e){throw e;}
        return retStr;
    }

    /**
     * ユーザーロックチェックを行う（パスワードを無視）
     * @return チェック結果(ロック：true ロックしない：false)
     * @throws Exception
     */
    private boolean isAccountLocked() throws Exception {
        SingletonS2ContainerFactory.init();
        JdbcManager jdbcManager = SingletonS2Container.getComponent(JdbcManager.class);

        SimpleWhere swh = new SimpleWhere().eq("mailAddress", this.emailAddress)
                .eq("deleteFlag", ConstantValue.deleteFlagEnabled)
                .in("authority", ConstantValue.authorityUserLv1, ConstantValue.authorityUserLv2);

        User user = jdbcManager.from(User.class)
                .where(swh)
                .getSingleResult()
                ;

        if (user == null) {
            return false;
        }

        this.userID    = user.userID;
        this.authority = user.authority;

        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.HOUR, -24);
        if (user.loginErrorAt != null && user.loginErrorAt.after(cal.getTime())){
            return true;
        }

        return false;

    }

    /**
     * ユーザーマスタの取得を行う
     * @throws Exception
     */
    private String getUser() throws Exception{
        String loginFlag = "";
        // S2Container初期化
        SingletonS2ContainerFactory.init();
        // S2ContainerからJdbcManagerを取得
        JdbcManager jdbcManager = SingletonS2Container.getComponent(JdbcManager.class);
        try{

            // アカウントロック判定
            if (isAccountLocked()) {
                return "6";
            }

            // 検索条件
            SimpleWhere swh = new SimpleWhere().eq("mailAddress", this.emailAddress)
                                               .eq("password", MakeHash.getSha256HashCode(this.password))
                                               .eq("deleteFlag", ConstantValue.deleteFlagEnabled)
                                               .in("authority", ConstantValue.authorityUserLv1, ConstantValue.authorityUserLv2);
            // 当日取得
            Calendar cal = Calendar.getInstance();
            // 24時間引く
            cal.add(Calendar.HOUR, -24);
/*            ComplexWhere cwh = new ComplexWhere().isNull("loginErrorAt", true)
                                                 .or()
                                                 .lt("loginErrorAt", cal.getTime());
*/
            // 一覧取得
            User user = jdbcManager.from(User.class)
                                     .where(swh)
                                     .getSingleResult()
                                     ;
            if(user != null){
                if(user.loginErrorAt != null && user.loginErrorAt.after(cal.getTime())){
                    // ロックされたの場合
                    loginFlag = "6";
                }else if(user.userIDFlag.equals(ConstantValue.userIDFlagProvisionalMode)){
                    // 仮ユーザーの場合
                    loginFlag = "4";
                }else if(user.loginPermit.equals("0")){
                    // ログインが許可されていない場合
                    loginFlag = "3";
                }else{
                    // 取得できた場合は仮パスワードで有効期限が切れてないかみる
                    if(user.passwordFlag != null && user.passwordFlag.equals(ConstantValue.passwordFlagProvisionalMode)){
                        if(!this.passwordExpiration()){
                            // 有効期限切れの場合は画面に戻す
                            loginFlag = "5";
                        }
                    }
                    if(loginFlag.equals("")){
                        // 取得できた場合は取得できた用にユーザーマスタを更新する
                        this.updateUserForFound(user);
                        if(user.passwordFlag.equals(ConstantValue.passwordFlagProvisionalMode)){
                            // 仮パスワードの場合
                            loginFlag = "2";
                        }else{
                            CommonService service = new CommonService();
                            String term = "-" + service.getPasswordChangeTerm();

                            // 時刻初期化
                            Calendar.getInstance().clear(Calendar.HOUR);
                            Calendar.getInstance().clear(Calendar.HOUR_OF_DAY);
                            Calendar.getInstance().clear(Calendar.DAY_OF_MONTH);
                            Calendar.getInstance().clear(Calendar.MONTH);
                            Calendar.getInstance().clear(Calendar.YEAR);
                            // 3ヶ月後
                            cal = Calendar.getInstance();
                            cal.add(Calendar.DAY_OF_MONTH, Integer.parseInt(term));
                            if(user.passwordUpdateAt != null){
                                if(user.passwordUpdateAt.before(new Timestamp(cal.getTime().getTime()))){
                                    // パスワード変更日付がxx日以上の場合
                                    loginFlag = "1";
                                }else{
                                    // パスワード変更日付がxx日未満の場合
                                    loginFlag = "0";
                                }
                            }else{
                                loginFlag = "0";
                            }
                        }
                    }
                }
                this.userID           = user.userID;
                this.authority        = user.authority;
                this.agreementFlag    = user.designAgreementFlag;
            }else{
                // 取得できなかった場合は取得できなかった用にユーザーマスタを更新する
                this.updateUserForNotFound();
            }
            return loginFlag;
        }catch(Exception e){
            throw e;
        }
    }

    /**
     * ユーザーマスタ更新(取得できた用)
     * @throws Exception
     */
    private void updateUserForFound(User user) throws Exception{
        // S2Container初期化
        SingletonS2ContainerFactory.init();
        // S2ContainerからJdbcManagerを取得
        JdbcManager jdbcManager = SingletonS2Container.getComponent(JdbcManager.class);
        try{

            // 当日取得
            Calendar cal = Calendar.getInstance();
            // プロパティの値を変更
            user.loginErrorCount = 0;
            user.loginErrorAt    = null;
            user.updatedAt       = new Timestamp(cal.getTime().getTime());
            user.updatedBy       = user.userID;

            // 更新
            jdbcManager.update(user).includes("loginErrorCount"
                                             ,"loginErrorAt"
                                             ,"updatedAt"
                                             ,"updatedBy"
                                             ).execute()
                                             ;
            return;
        }catch(Exception e){
            throw e;
        }
    }

    /**
     * ユーザーマスタ更新(取得できなかった用)
     * @throws Exception
     */
    private void updateUserForNotFound() throws Exception{
        // S2Container初期化
        SingletonS2ContainerFactory.init();
        // S2ContainerからJdbcManagerを取得
        JdbcManager jdbcManager = SingletonS2Container.getComponent(JdbcManager.class);
        try{
            // 検索条件
            SimpleWhere swh = new SimpleWhere().eq("mailAddress", this.emailAddress);

            // 一覧取得
            User user = jdbcManager.from(User.class)
                                     .where(swh)
                                     .getSingleResult()
                                     ;

            if(user == null){
                return;
            }else{
                // 当日取得
                Calendar cal = Calendar.getInstance();
                // プロパティの値を変更
                user.loginErrorCount = user.loginErrorCount + 1;
                if(user.loginErrorCount >= 3 && user.loginErrorAt == null){
                    // アカウントがロックされてなくて、ログイン回数が3回以上の場合はアカウントロックする
                    user.loginErrorAt = new Timestamp(cal.getTime().getTime());
                }
                user.updatedAt       = new Timestamp(cal.getTime().getTime());
                user.updatedBy       = user.userID;

                // 更新
                jdbcManager.update(user).includes("loginErrorCount"
                                                                ,"loginErrorAt"
                                                                ,"updatedAt"
                                                                ,"updatedBy"
                                                                ).execute()
                                                                ;
            }

            return;
        }catch(Exception e){
            throw e;
        }
    }

    /**
     * 仮パスワードが有効かを見る
     * @return true:有効期限内 false:有効期限切れ
     * @throws Exception
     */
    private boolean passwordExpiration() throws Exception{
        // S2Container初期化
        SingletonS2ContainerFactory.init();
        // S2ContainerからJdbcManagerを取得
        JdbcManager jdbcManager = SingletonS2Container.getComponent(JdbcManager.class);
        try{

            Calendar cal = Calendar.getInstance();
            // 24時間引く
            cal.add(Calendar.HOUR, -24);
            ComplexWhere cwh = new ComplexWhere().isNotNull("passwordUpdateAt", true)
                                                 .lt("passwordUpdateAt", cal.getTime());
            // 検索条件
            SimpleWhere swh = new SimpleWhere().eq("mailAddress", this.emailAddress)
                                               .eq("passwordFlag", ConstantValue.passwordFlagProvisionalMode)
                                               ;

            // 一覧取得
            User user = jdbcManager.from(User.class)
                                   .where(swh, cwh)
                                   .getSingleResult()
                                   ;

            if(user == null){
                return true;
            }else{
                return false;
            }
        }catch(Exception e){
            throw e;
        }
    }

    /**
     * お知らせのタイトルを取得
     * @return 取得結果
     * @throws Exception
     */
    public List<Information> getSubject() throws Exception{
        // お知らせリスト
        informationList = new ArrayList<Information>();
        // S2Container初期化
        SingletonS2ContainerFactory.init();
        // S2ContainerからJdbcManagerを取得
        JdbcManager jdbcManager = SingletonS2Container.getComponent(JdbcManager.class);
        try{
            Calendar cal = Calendar.getInstance();
            // 検索条件
            informationList = jdbcManager.from(Information.class)
                                              .where(" ? <= endTime and deleteFlag like '0' ",cal.getTime())
                                              .orderBy("createdAt desc ")
                                              .getResultList();

        }catch(Exception e){
            throw e;
        }
        return informationList;
    }
}